﻿using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Web.Mvc;
using BLL.Services;
using BLL.Services.Books;
using BLL.Services.Books.Listing;
using BLL.Services.Users;
using MvcContrib.Sorting;
using MvcContrib.UI.Grid;
using Web.Areas.Admin.Infrastructure;
using Web.Areas.Admin.Models.Books;
using Web.Infrastructure;
using Web.Infrastructure.Models;
using Web.Infrastructure.Security;

namespace Web.Areas.Admin.Controllers
{
    /// <summary>
    /// The books controller.
    /// </summary>
    [AdminAuthorization]
    public partial class BooksController : AdminController
    {
        private readonly IBookService _booksService;

        private readonly IUsersService _usersService;

        public BooksController(IBookService booksService, IUsersService usersService)
        {
            _booksService = booksService;
            _usersService = usersService;
        }

        public virtual ActionResult Index()
        {
            return BackBoneView(MVC.Admin.Shared.Views.Empty);
        }

        public virtual ActionResult ListingTemplate()
        {
            return BackBoneView(MVC.Admin.Books.Views.Listing);
        }

        [ListingAction("Name")]
        public virtual ActionResult Listing(GridSortOptions sort, int size, int page, BookFilter filter)
        {
            var model = _booksService.GetListingBook(
                page, size, sort.Column, sort.Direction != SortDirection.Descending ? 0 : 1, filter);
            return BackBoneJson(model);
        }

        public virtual ActionResult GetUsers(int? bookId)
        {
            if (bookId.HasValue)
            {
                var book = _booksService.GetBookById(bookId.Value);
                if (book != null)
                {
                    return
                        Json(
                            _usersService.GetAllUsers.Select(
                                x =>
                                new SelectListItem
                                    {
                                        Text = x.Email,
                                        Value = x.UserId.ToString(CultureInfo.InvariantCulture),
                                        Selected = x.UserId == book.UserId
                                    }),
                            JsonRequestBehavior.AllowGet);
                }
            }
            return Json(
                _usersService.GetAllUsers.Select(
                    x =>
                    new SelectListItem
                        {
                            Text = x.Email,
                            Value = x.UserId.ToString(CultureInfo.InvariantCulture)
                        }),
                JsonRequestBehavior.AllowGet);
        }

        /// <summary>
        /// Deletes selected items.
        /// </summary>
        /// <param name="items">Items to delete.</param>
        public virtual ActionResult Delete(int[] items)
        {
            var model = new BaseModel();
            foreach (var item in items)
            {
                try
                {
                    _booksService.Delete(item);
                }
                catch (ServiceException exception)
                {
                    ModelState.AddModelError(string.Empty, "Could not delete book with id " + item);
                    Trace.TraceError(exception.ToString());
                }
            }
            model.Errors = GetErrors;
            if (ModelState.IsValid)
            {
                model.SuccessMessage = "Book have been successfully deleted.";
            }
            return Json(model);
        }

        [HttpGet]
        public virtual ActionResult Create()
        {
            return BackBoneView(MVC.Admin.Shared.Views.Empty);
        }

        /// <summary>
        /// Show form for create Book
        /// </summary>
        public virtual ActionResult CreateTemplate()
        {
            return BackBoneView(MVC.Admin.Books.Views.Create, new BookCreateModel());
        }

        /// <summary>
        /// Creates the specified model.
        /// </summary>
        /// <param name="model">The model.</param>
        [HttpPost]
        public virtual ActionResult Create(BookCreateModel model)
        {
            if (!ModelState.IsValid)
            {
                model.Errors = GetErrors;
                return Json(model);
            }
            var book = (Book)model;
            try
            {
                _booksService.Create(book);
                model.SuccessMessage = "Book has been successfully created.";
                return Json(model);
            }
            catch (ServiceException exception)
            {
                ModelState.AddModelError(string.Empty, exception.Message);
                model.Errors = GetErrors;
                return Json(model);
            }
        }

        /// <summary>
        /// Show form for editing the specified book.
        /// </summary>
        /// <param name="bookId">
        /// The book Id.
        /// </param>
        [HttpGet]
        public virtual ActionResult Edit(int? bookId)
        {
            var model = new BookEditModel();
            if (!bookId.HasValue)
            {
                model.Errors = new List<ErrorModel>
                    {
                        new ErrorModel("Empty value")
                    };
                return BackBoneJson(model);
            }
            var book = _booksService.GetBookById(bookId.Value);

            if (null == book)
            {
                model.Errors = new List<ErrorModel>
                    {
                        new ErrorModel(string.Format("Book {0} was not found.", bookId))
                    };
                return BackBoneJson(new BookEditModel());
            }

            model = new BookEditModel(book);

            return BackBoneJson(model);
        }

        [HttpGet]
        public virtual ActionResult EditTemplate()
        {
            return PartialView(MVC.Admin.Books.Views.Edit, new BookEditModel());
        }

        /// <summary>
        /// Save the specified Book.
        /// </summary>
        /// <param name="bookId">The Author id.</param>
        /// <param name="model">The model.</param>
        [HttpPost]
        public virtual ActionResult Edit(int bookId, BookEditModel model)
        {
            if (!ModelState.IsValid)
            {
                model.Errors = GetErrors;
                return Json(model);
            }

            var book = (Book)model;
            try
            {
                _booksService.Save(book);

                model.SuccessMessage = "Book has been successfully updated.";

                return Json(model);
            }
            catch (ServiceException exception)
            {
                ModelState.AddModelError(string.Empty, exception.Message);
                model.Errors = GetErrors;
                return Json(model);
            }
        }

        public virtual ActionResult Validate(int? bookId, string name, int[] authors)
        {
            var idParam = bookId.HasValue ? bookId.Value : 0;
            var result = _booksService.ValidateBook(idParam, name, authors);
            return Json(result);
        }
    }
}
